package com.example.ktdemo.anim

import android.content.Context
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View

/**
 * FileName: AnimRippleView
 * Author: lzt
 * Date: 2023/3/13 10:19
 * 水波纹动画view
 */
class AnimRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {

    private var mStart = false

    private var mPaint = Paint()

    private var mWidth = 0
    private var mHeight = 0

    private val LOCK = Object()

    //绘制的信息
    private var mDrawInfo: AnimRippleInfo = AnimRippleInfo()

    //绘制中间变量
    private var mDrawCircleRadius = 0f

    //水波纹半径集合
    private var mDrawRippleList: MutableList<Int> = ArrayList()

    //水波纹间距
    private var mDrawRippleInterval = 10

    //水波纹刷新速率
    private var mDrawRippleRate = 2

    init {
        mPaint.style = Paint.Style.STROKE
        mPaint.strokeWidth = 1f
        mPaint.isAntiAlias = true
        mPaint.isDither = true
        mPaint.textAlign = Paint.Align.LEFT
    }

    /**
     * 重置绘制参数
     * */
    private fun resetDrawInfo() {
        //圆的半径
        mDrawCircleRadius =
            ((mWidth.coerceAtMost(mHeight) / 2).toFloat()) * mDrawInfo.circleRadiusRate
        mDrawRippleInterval = (mDrawCircleRadius / 5).toInt()

    }

    /**
     * 是否需要绘制
     * */
    private fun needToDraw(): Boolean {
        mWidth = measuredWidth
        mHeight = measuredHeight
        return mWidth != 0 && mHeight != 0 && VISIBLE == visibility
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if (!needToDraw() || canvas == null) {
            return
        }
        resetDrawInfo()
        //开始绘制
        canvas.save()
        //中心圆---------------------------------------------------------------------------------
        mPaint.style = Paint.Style.FILL
        mPaint.color = mDrawInfo.circleColor
        mPaint.alpha = 255
        canvas.drawCircle(mWidth / 2f, mHeight / 2f, mDrawCircleRadius, mPaint)


        //水波纹---------------------------------------------------------------------------------
        if (mStart) {

            if (mDrawRippleList.isEmpty()) {
                //初始化
                val startRadius = mDrawCircleRadius
                mDrawRippleList.add((startRadius).toInt())
            } else {
                //检查是否需要插入
                val lastInfo = mDrawRippleList.lastOrNull()
                if (lastInfo != null) {
                    if (lastInfo - mDrawCircleRadius > mDrawRippleInterval) {
                        //需要插入了
                        val startRadius = mDrawCircleRadius
                        mDrawRippleList.add(startRadius.toInt())
                    }
                }
            }
            //开始绘制水波纹
            mPaint.color = mDrawInfo.rippleColor
            mPaint.strokeWidth = 2f
            mPaint.style = Paint.Style.STROKE
            for (pos in 0 until mDrawRippleList.size) {
                val radius = mDrawRippleList[pos]
                //计算透明度
                val radiusInterval = radius - mDrawCircleRadius
                val totalInterval = (mWidth / 2.coerceAtMost(mHeight / 2)) - mDrawCircleRadius
                val alpha = radiusInterval * 1f / totalInterval
                mPaint.alpha = (255 * (1 - alpha)).toInt()
                canvas.drawCircle(mWidth / 2f, mHeight / 2f, radius.toFloat(), mPaint)
            }
            //检查数据并且递增
            val trainList: MutableList<Int> = ArrayList()
            for (pos in 0 until mDrawRippleList.size) {
                val radius = mDrawRippleList[pos]
                if (radius < (mWidth / 2).coerceAtMost(mHeight / 2)) {
                    trainList.add(radius)
                }
            }

            for (pos in 0 until trainList.size) {
                val radius = trainList[pos]
                trainList[pos] = radius + mDrawRippleRate
            }

            //替换原来的绘制列表
            mDrawRippleList.clear()
            mDrawRippleList.addAll(trainList)
        }

        canvas.restore()

        postInvalidate()
    }

    //外部调用---------------------------------------------------------------------

    fun start(info: AnimRippleInfo = AnimRippleInfo()) {
        synchronized(LOCK) {
            this.mDrawInfo = info
            this.mStart = true
            post(Runnable {
                postInvalidate()
            })
        }
    }

    fun stop() {
        synchronized(LOCK) {
            this.mStart = false
            post(Runnable {
                postInvalidate()
            })
        }
    }

}